package com.tbit.uqbike.client.service.ordertrace;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 优先级队列
 *
 *
 * @author <a href="mailto:chen.chaoxiong@tbit.com.cn">ChenChaoXiong</a>
 * @since 2024/8/2
 */
@Service
@Slf4j
public class PriorityQueueService {


    private final RedisTemplate<String, String> redisTemplate;

    public PriorityQueueService(RedisTemplate<String, String> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 入队
     * 以时间戳为优先级
     * @param groupId    group ID
     * @param message   message
     * @param timestamp 消息的时间戳
     * @param expireSecondTime 过期时间（秒）
     */
    public void enqueue(String groupId, String message, double timestamp, int expireSecondTime) {
        log.info("enqueue message: {} to group: {} with timestamp: {}", message, groupId, timestamp);
        redisTemplate.opsForZSet().add(groupId, message, timestamp);
        redisTemplate.expire(groupId, expireSecondTime, TimeUnit.SECONDS);
    }

    /**
     * 获取排名最高的消息
     * 不删除
     *
     * @param groupId  group ID
     * @return 返回最新的消息或者null(如果队列为空)
     */
    public String peek(String groupId) {
        return getMessage(groupId, false);
    }

    /**
     * 出队
     * 删除
     *
     * @param groupId  group ID
     * @return 返回最新的消息或者null(如果队列为空)
     */
    public String dequeue(String groupId) {
        log.info("dequeue message from group: {}", groupId);
        return getMessage(groupId, true);
    }



    /**
     * 获取最新的消息
     *
     * @param groupId  group ID
     * @param remove  是否删除
     * @return 返回最新的消息或者null(如果队列为空)
     */
    private String getMessage(String groupId, boolean remove) {
        //由低到高排序，取第一个
        Set<String> messages = redisTemplate.opsForZSet().range(groupId, 0, 0);
        log.info("get message: {} from group: {},remove flag: {}", messages, groupId,remove);
        if (messages != null && !messages.isEmpty()) {
            String message = messages.iterator().next();
            if (remove) {
                redisTemplate.opsForZSet().remove(groupId, message);
            }
            return message;
        }
        return null;
    }

    /**
     * 获取消息和分数并清空全部消息
     * @param groupId
     * @return
     */
    public Map<String, Double> getAllMessages(String groupId) {
        Set<ZSetOperations.TypedTuple<String>> tuples = redisTemplate.opsForZSet().rangeWithScores(groupId, 0, -1);
        if (tuples == null || tuples.isEmpty()) {
            return Collections.emptyMap();
        }
        Map<String, Double> messages = tuples.stream()
            .collect(Collectors.toMap(ZSetOperations.TypedTuple::getValue, ZSetOperations.TypedTuple::getScore));
        redisTemplate.delete(groupId);
        return messages;
    }

}